﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ActiveStory.DataManager;
using System.Xml;
using System.IO;
using ActiveStory.IO.XmlElementNames;

namespace ActiveStory.Exporter
{
    public class ActiveStorySilverlightExporter : IActiveStoryExporter
    {
        string _settingsFileName = "ActiveStorySettings.slsx";
        String _exportPath = null;
        #region IActiveStoryExporter Members
        
        /// <summary>
        /// Exports the given project to appropriate state
        /// for hosting on an ASP.NET web server, the path must be the
        /// directory where the website is hosted (or any other directory
        /// if manually deploying.)
        /// </summary>
        /// <param name="project"></param>
        /// <param name="path"></param>
        /// <param name="startupPage"></param>
        /// <param name="parameters">Only one string, the task instructions.</param>
        public void Export(ActiveStoryProject project, string path, int startupPage, params string[] parameters)
        {
            if (parameters.Length != 1)
                return;
            _exportPath = path;
            foreach (ActiveStoryPageMetadata currentPage in project.PageLookupTable.Values)
            {
                ExportPageData(project.ProjectName, currentPage, path);
            }
            ExportProjectFile(project, path, startupPage);
            ExportSettings(project, parameters[0]);
        }

        private void ExportSettings(ActiveStoryProject project, String taskInstructions)
        {
            string filename = GetAbsolutePath(_settingsFileName);
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.Indent = true;
            xws.CloseOutput = true;
            XmlWriter xw = XmlWriter.Create(filename, xws);
            xw.WriteStartDocument();
            xw.WriteStartElement(SilverlightSettingsXmlNames.RootElement);

            xw.WriteStartElement(SilverlightSettingsXmlNames.ProjectFileLocationElement);
            xw.WriteValue(CreateProjectFilename(project.ProjectName));
            xw.WriteEndElement();

            xw.WriteStartElement(SilverlightSettingsXmlNames.TaskInstructionsElement);
            xw.WriteValue(System.Security.SecurityElement.Escape(taskInstructions));
            xw.WriteEndElement();

            xw.WriteEndElement();   //End Root Element
            xw.WriteEndDocument();
            xw.Flush();
            xw.Close();
        }

        private void ExportPageData(string projectName, ActiveStoryPageMetadata pageMetadata, string path)
        {
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.Indent = true;
            xws.CloseOutput = true;
            string filename = GetAbsolutePath(CreatePageFilename(projectName, pageMetadata.PageNumber));
            XmlWriter xw = XmlWriter.Create(filename, xws);
            xw.WriteStartDocument();
            xw.WriteStartElement(PageSilverlightXmlNames.RootElement);

            xw.WriteStartElement(PageSilverlightXmlNames.PageNumberElement);
            xw.WriteValue(pageMetadata.PageNumber);
            xw.WriteEndElement();

            File.Copy(ActiveStory.IO.FileManager.GetAbsolutePath(pageMetadata.ThumbnailFileLocation), GetAbsolutePath(CreateImageFilename(projectName, pageMetadata.PageNumber)), true);
            

            xw.WriteStartElement(PageSilverlightXmlNames.PageImageElement);
            xw.WriteValue(CreateImageFilename(projectName, pageMetadata.PageNumber));
            xw.WriteEndElement();

            xw.WriteStartElement(PageSilverlightXmlNames.ButtonDetailCollectionElement);

            IO.XmlMapFileReader<int, int> xmfr = new IO.XmlMapFileReader<int, int>();
            Dictionary<int, int> buttonMap = (Dictionary<int, int>)xmfr.ParseFile(ActiveStory.IO.FileManager.GetAbsolutePath(pageMetadata.ButtonToPageMapFileLocation), ButtonFileXmlNames.RootElement, ButtonFileXmlNames.ItemElement,
                ButtonFileXmlNames.ButtonNumberElement, ButtonFileXmlNames.PageNumberElement);

            System.Windows.Controls.InkCanvas tempInkCanvas = new System.Windows.Controls.InkCanvas();
            ActiveStoryApplication.ImportXaml(ref tempInkCanvas, pageMetadata.XamlFileLocation);

            xw.WriteStartElement(PageSilverlightXmlNames.ButtonCountElement);
            xw.WriteValue(buttonMap.Count);
            xw.WriteEndElement();

            foreach (System.Windows.UIElement item in tempInkCanvas.Children)
            {
                if (item.GetType() != typeof(System.Windows.Controls.Button))
                    continue;
                System.Windows.Controls.Button tempButton = (System.Windows.Controls.Button)item;

                xw.WriteStartElement(PageSilverlightXmlNames.ButtonDetailElement);

                xw.WriteStartElement(PageSilverlightXmlNames.ButtonTopElement);
                xw.WriteValue(System.Windows.Controls.InkCanvas.GetTop(tempButton));
                xw.WriteEndElement();

                xw.WriteStartElement(PageSilverlightXmlNames.ButtonLeftElement);
                xw.WriteValue(System.Windows.Controls.InkCanvas.GetLeft(tempButton));
                xw.WriteEndElement();

                xw.WriteStartElement(PageSilverlightXmlNames.ButtonWidthElement);
                xw.WriteValue(tempButton.Width);
                xw.WriteEndElement();

                xw.WriteStartElement(PageSilverlightXmlNames.ButtonHeightElement);
                xw.WriteValue(tempButton.Height);
                xw.WriteEndElement();

                xw.WriteStartElement(PageSilverlightXmlNames.ButtonContentElement);
                xw.WriteValue(tempButton.Content);
                xw.WriteEndElement();

                xw.WriteStartElement(PageSilverlightXmlNames.ButtonTargetPageElement);
                if(buttonMap.ContainsKey((int)tempButton.Content))
                    xw.WriteValue(buttonMap[(int)tempButton.Content]);    
                else
                    xw.WriteValue(-1);    
                xw.WriteEndElement();

                xw.WriteEndElement();
            }



            xw.WriteEndElement();   //End Button Collection Element

            xw.WriteEndElement();   //End Root Element
            xw.WriteEndDocument();
            xw.Flush();
            xw.Close();
        }

        private void ExportProjectFile(ActiveStoryProject project, string path, int startupPage)
        {
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.Indent = true;
            xws.CloseOutput = true;
            string filename = GetAbsolutePath(CreateProjectFilename(project.ProjectName));
            XmlWriter xw = XmlWriter.Create(filename, xws);
            xw.WriteStartDocument();
            xw.WriteStartElement(ProjectSilverlightXmlNames.RootElement);

            xw.WriteStartElement(ProjectSilverlightXmlNames.ProjectNameElement);
            xw.WriteValue(project.ProjectName);
            xw.WriteEndElement();

            xw.WriteStartElement(ProjectSilverlightXmlNames.StartupPageElement);
            xw.WriteValue(startupPage);
            xw.WriteEndElement();

            xw.WriteStartElement(ProjectSilverlightXmlNames.PageCollectionElement);

            xw.WriteStartElement(ProjectSilverlightXmlNames.PageCountElement);
            xw.WriteValue(project.PageLookupTable.Count);
            xw.WriteEndElement();

            foreach (KeyValuePair<int,ActiveStoryPageMetadata> PagePair in project.PageLookupTable)
            {
                xw.WriteStartElement(ProjectSilverlightXmlNames.PageFileElement);

                xw.WriteStartElement(ProjectSilverlightXmlNames.PageNumberElement);
                xw.WriteValue(PagePair.Key);
                xw.WriteEndElement();

                xw.WriteStartElement(ProjectSilverlightXmlNames.PageFileLocationElement);
                xw.WriteValue(CreatePageFilename(project.ProjectName, PagePair.Value.PageNumber));
                xw.WriteEndElement();

                xw.WriteEndElement();
            }

            

            xw.WriteEndElement();   //End Page Collection Element

            xw.WriteEndElement();   //End Root Element
            xw.WriteEndDocument();
            xw.Flush();
            xw.Close();
        }

        private string CreateProjectFilename(string projectName)
        {
            return projectName + ActiveStoryApplication.ProjectSilverlightExportExtension;
        }

        private string CreatePageFilename(string projectName, int pageNumber)
        {
            return projectName + "-" + pageNumber + ActiveStoryApplication.PageSilverlightExportExtension;
        }

        private string CreateImageFilename(string projectName, int pageNumber)
        {
            return projectName + "-" + pageNumber + ActiveStoryApplication.ImageFileExtension;
        }

        private string GetAbsolutePath(string filename)
        {
            return Path.Combine(_exportPath, filename);
        }
        #endregion
    }
}
